import java.util.LinkedList;

/**
 * Authors - Oren Bracha, Rony Lahav & Yehuda Eterman
 * This class handles the REQUESTENTRY and REQUESTPICTURE messages.
 * It gets the number of expected messages and stores their data.
 * It returns the missing entry messages or pictures fragment or returns that we got them all.
 * Only when it has all the parts it was supposed to receive it returns the received content itself.
 */

public class RequestsManager {

	private String[] data;
	private String[] prevData;
	private String[] picture;
	private DBTuple[] tuple;
	private int numOfFirstSegment;
	private boolean isEntryReq;
	private int counter;
	
	//initializes vars according to the request type of entry or picture
	public RequestsManager(int arrSize, int numOfFirstSegment){
		this.numOfFirstSegment = numOfFirstSegment;
		this.isEntryReq = (numOfFirstSegment == 0);
		data = new String[arrSize];
		if (this.isEntryReq)
			tuple = new DBTuple[arrSize];
		else
			picture = new String[arrSize];
		counter = 0;
	}
	
	/* gets a message and updates its location in the messages list
	   by scanning the list in accordance to the SN received and in the relevant location
	   inserts the peername to "remember" what peers still need to be updated if needed,
	   or the fragment number to "remember" which missing picture fragments are still needed.
	   It also stores the updates themselves so that when we got all requests we can get them for the actual update.
	   This means that the DB update doesn't happen unless we got the entire "N" messages required.*/
	public void updateEntry(int location, String peerName, DBTuple tp, String pic,  boolean firstTime){
		if (isComplete())
			return;
		//at the first run each location is directly the position for the current peername/fragment
		if (firstTime){
			data[location-1] = peerName;
			if (isEntryReq){
				tuple[location-1] = tp;
			}
			else{
				picture[location-1] = pic;
			}
			
			++counter;
		}
		else{
			int loc = 0;
			int emptyCount=0;
			boolean done = false;
			/*the location is actually the number of "holes" in the array we need to skip
			  until reaching the right position to store the current peername/fragment*/
			while (loc<prevData.length && !done){
				if (prevData[loc] == null || prevData[loc].equals(""))
					++emptyCount;
				if (emptyCount == location)
					done=true;
				else
					++loc;
			}
			data[loc] = peerName;
			if (isEntryReq)
				tuple[loc] = tp;
			else
				picture[loc] = pic;
			/*The counter tells us how many requests we got to see if we got them all.
			  the storing process it built in a way that we can't get "extra" requests,
			  and that's due to the use of DBCopy, thus each new request is surely a new one and it is counted*/
			++counter;
		}
	}
	
	//if all the list is full with peer names we finishes getting all needed requests
	public boolean isComplete(){
		if (counter < data.length)
			return false;
		else
			return true;
	}
	
	/*returns ranges of "holes" in the list to create new requests with ranges of missing packages.
	  this is the only way missing entries will be returned so we create new entry requests only with ranges*/
	public LinkedList<String[]> getRangesList(){
		LinkedList<String[]> list = new LinkedList<String[]>();
		int ind=0;
		String first, last;
		String[] range;
		while (ind<data.length){
			//null or "" are "holes"
			while (ind<data.length && !(data[ind] == null || data[ind].equals("")))
				++ind;
			if (ind<data.length){
				if (ind != 0)
					first = data[ind-1];
				else
					first = "0";
				while (ind<data.length && (data[ind] == null || data[ind].equals("")))
					++ind;
				if (ind == data.length)
					last = "ALL";
				else
					last = data[ind];
				range = new String[2];
				range[0]=first;
				range[1]=last;
				list.add(range);
				++ind;
			}
		}
		prevData = data.clone();
		return list;
	}
	
	/*returns a list of all the missing fragments for RequestPicture.
	  this is the only way we return missing fragments so we create new picture requests only with lists*/
	public String getMissingFragmentsList(){
		String list = "";
		for (int i=0;i<picture.length;++i) {
			if (picture[i] == null || picture[i].equals(""))
				list += Integer.toString(i+numOfFirstSegment) + ",";
		}
		prevData = data.clone();
		if (list.equals(""))
			return null;
		else
			return list.substring(0, list.length()-1);
	}
	
	//returns the picture data as collected and stored (in the right order)
	public String[] getPicture(){
		return picture;
	}
	
	//returns the stored entries
	public DBTuple[] getEntries(){
		return tuple;
	}
	
}
